﻿using MQTTnet.Server;
using MQTTnet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Collections.Concurrent;
using System.Threading;
using System.Diagnostics;

namespace HostComputer
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

     

        #region MQTT

        private void startMqttServerBtn_Click(object sender, EventArgs e)
        {
            /*
        * This sample starts a simple MQTT server which will accept any TCP connection.
        */

            var mqttFactory = new MqttFactory();

            // The port for the default endpoint is 1883.
            // The default endpoint is NOT encrypted!
            // Use the builder classes where possible.
            MqttServerOptions mqttServerOptions = new MqttServerOptionsBuilder().WithDefaultEndpoint()

                .Build();


            // The port can be changed using the following API (not used in this example).
            // new MqttServerOptionsBuilder()
            //     .WithDefaultEndpoint()
            //     .WithDefaultEndpointPort(1234)
            //     .Build();

            using (var mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions))

            {
                /*mqttServer.ValidatingConnectionAsync += (context) => {

                    return true;
                };*/

                 mqttServer.StartAsync();

                Console.WriteLine("Press Enter to exit.");
                Console.ReadLine();

                // Stop and dispose the MQTT server if it is no longer needed!
                 mqttServer.StopAsync();
            }
        }


        #endregion

        ConcurrentDictionary<Socket, ClientContext> clientMap;

        Socket server;

        CancellationTokenSource cancellationTokenSource;

        private void startServerBtn_Click(object sender, EventArgs e)
        {

            if (startServerBtn.Text == "关闭服务器") {
                startServerBtn.Text = "启动服务器";
                cancellationTokenSource.Cancel();
                
                return;
            }
            server?.Close();

            cancellationTokenSource = new CancellationTokenSource();


            server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

            server.Bind(new IPEndPoint(IPAddress.Any,39999));
            server.Listen(10);

            clientMap = new ConcurrentDictionary<Socket, ClientContext>();

            var token = cancellationTokenSource.Token;

            Task.Run(() =>
            {
                while (!token.IsCancellationRequested) {
                    if (server.Poll(100, SelectMode.SelectRead)) { 
                        Socket client = server.Accept();
                        clientMap.TryAdd(client,new ClientContext());
                    }
                    foreach (KeyValuePair<Socket, ClientContext> kv in clientMap)

                    {

                        Socket client = kv.Key;

                        if (client.Poll(100, SelectMode.SelectRead))
                        {

                            byte[] buf = new byte[256];

                            if (client.Receive(buf) == 0)
                            {

                                return;
                            }

                            kv.Value.process(buf);
                        }
                    }
                    

                }
                
            }, token);

            startServerBtn.Text = "关闭服务器";
        }

     

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            ParametersContext.a = 1f * trackBar1.Value/100;

            Console.WriteLine(ParametersContext.a);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            yaw_lab.Text = ParametersContext.yaw.ToString();
            pitch_lab.Text = ParametersContext.pitch.ToString();
            roll_lab.Text = ParametersContext.roll.ToString();
            a_lab.Text = ParametersContext.a.ToString();
        }
    }
}
